# LuckPay Web Manage System
#
# Copyright (c) 2016 Lucky Byte, Inc.
#
express = require 'express'
fs      = require 'fs'
path    = require 'path'
uuid    = require 'uuid'
pgsql   = require 'pg'
moment  = require 'moment'
mkdirp  = require 'mkdirp'
pgcopy  = require 'pg-copy-streams'
multer  = require 'multer'
mmm     = require 'mmmagic'

router  = express.Router()
module.exports = router

router.all '/', (req, res, next) ->
    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    where_clause = "(
        bin_num like $1 or card_name like $1 or
        issuer_code like $1 or issuer_name like $1
    )"
    if req.body.card_type and req.body.card_type.length > 0
        where_clause += " and card_type = '#{req.body.card_type}'"
        res.locals.card_type = req.body.card_type

    # 查询记录总数
    await client.query \
        "select count(*) as count from pay_cardbin where #{ where_clause }",
        ['%' + res.locals.keyword + '%'], defer err, result
    if err then done(client); return next(err)
    res.locals.total = result.rows[0].count

    # 查询当前页面中显示的记录
    await client.query \
        "select * from pay_cardbin where #{ where_clause }
            order by serial offset $2::int limit $3::int", [
            '%' + res.locals.keyword + '%',
            res.locals.offset,
            res.locals.page_rows
        ], defer err, result
    if err then done(client); return next(err)
    done()
    res.render 'cardbin/index', records: result.rows


router.get '/export', (req, res, next) ->
    res.locals.breadcrumbs.push 'title': '导出数据'
    res.render 'cardbin/export'


router.post '/export', (req, res, next) ->
    for k in ['delim', 'encoding']
        return next(new Error("请求缺少参数[#{k}]")) if not req.body[k]

    if req.body.delim == 'comma'
        delimiter = ','
    else if req.body.delim == 'pipe'
        delimiter = '|'
    else if req.body.delim == 'semicolon'
        delimiter = ';'
    else
        return next(new Error('无效的分隔符参数'))

    # 数据库 COPY TO 输出文件
    dirname = settings.dnload_path + "/cardbin"
    mkdirp.sync(dirname)
    today = moment().format('YYYY-MM-DD')
    dnfile = "#{dirname}/cardbin-#{today}.txt"

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    stream = client.query pgcopy.to("copy pay_cardbin to STDOUT
        with encoding '#{req.body.encoding}' delimiter '#{delimiter}' NULL ''",
        highWaterMark: 10)
    down_stream = fs.createWriteStream(dnfile, highWaterMark: 10)

    stream.on 'end', ->
        down_stream.close()
        await res.download dnfile, path.basename(dnfile), defer err
        fs.unlink dnfile, (err) -> if err then console.error err
        res.end()
        client.end()
    stream.on 'error', (err) ->
        console.error err.message
    stream.pipe down_stream


router.get '/import', (req, res, next) ->
    res.locals.breadcrumbs.push 'title': '导入数据'
    res.render 'cardbin/import'


uploader = multer(dest: settings.upload_path)
router.post '/import', uploader.single('attach_file'), (req, res, next) ->
    for k in ['delim', 'encoding']
        return next(new Error("请求缺少参数[#{k}]")) if not req.body[k]
    if not req.file
        return next(new Error("请求缺少上传数据文件."))

    # 检查文件类型是否为文本文件
    magic = new mmm.Magic(mmm.MAGIC_MIME_TYPE)
    await magic.detectFile req.file.path, defer err, result
    if err
        fs.unlink req.file.path, (err) -> if err then console.error err
        return next(new Error('不能检测文件类型，导入失败'))
    if result != 'text/plain'
        fs.unlink req.file.path, (err) -> if err then console.error err
        return next(new Error('上传的文件格式非文本文件，请检查'))

    if req.body.delim == 'comma'
        delimiter = ','
    else if req.body.delim == 'pipe'
        delimiter = '|'
    else if req.body.delim == 'semicolon'
        delimiter = ';'
    else
        return next(new Error('无效的分隔符参数'))

    # 将上传文件保存到指定的目录待后续处理
    dest_path = "#{settings.upload_path}/cardbin"
    mkdirp.sync(dest_path)
    today = moment().format('YYYY-MM-DD')
    dest_file = "#{dest_path}/cardbin-#{today}.txt"
    fs.rename req.file.path, dest_file

    await pgsql.connect settings.pgsql_url, defer err, client, done
    if err then done(client); return next(err)

    await client.query "begin", defer err, result
    await client.query "delete from pay_cardbin", defer err, result

    stream = client.query pgcopy.from("copy pay_cardbin from STDIN
        with encoding '#{req.body.encoding}' delimiter '#{delimiter}' NULL ''",
        highWaterMark: 10)

    stream.on 'error', (err) ->
        await client.query "rollback", defer err, result
        fs.unlink dest_file, (err) -> if err then console.error err
        done(client);
        return next(err)

    file_stream = fs.createReadStream dest_file, highWaterMark: 10
    file_stream.on 'end', ->
        await client.query "commit", defer err, result
        done()
        return res.redirect '/cardbin'
    file_stream.on 'error', (err) ->
        await client.query "rollback", defer err, result
        done()
        return next(err)
    file_stream.pipe stream
